using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;

namespace miciv.Rendering
{
    public class VertexDefinition
    {
        public class Element
        {
            protected string m_strID;
            public string ID
            {
                get
                {
                    return this.m_strID;
                }
            }

            protected Type m_type;
            public Type Type
            {
                get
                {
                    return this.m_type;
                }
            }

            public Element(XmlElement _xmlElement)
            {
                this.m_strID = _xmlElement.Attributes["id"].Value;
                this.m_type = Type.GetType(_xmlElement.Attributes["type"].Value, true);
                if (null == this.m_type)
                {
                    throw new Exception(string.Format("{0} : unknown {1} type.", this.GetType().FullName, _xmlElement.Attributes["type"].Value));
                }
            }
        }

        public class Interface
        {
            protected string m_strID;
            public string ID
            {
                get
                {
                    return this.m_strID;
                }
            }

            public Interface(XmlElement _xmlElement)
            {
                this.m_strID = _xmlElement.Attributes["id"].Value;
            }
        }

        protected List<Element> m_lstElements;
        protected List<Interface> m_lstInterfaces;

        protected string m_strID;
        public string ID
        {
            get
            {
                return this.m_strID;
            }
        }

        public int ElementCount
        {
            get
            {
                return this.m_lstElements.Count;
            }
        }

        public IEnumerable Elements
        {
            get
            {
                return this.m_lstElements;
            }
        }

        public int InterfaceCount
        {
            get
            {
                return this.m_lstInterfaces.Count;
            }
        }

        public IEnumerable Interfaces
        {
            get
            {
                return this.m_lstInterfaces;
            }
        }

        public VertexDefinition(XmlElement _xmlVertexDefinition)
        {
            this.m_lstElements = new List<Element>();
            this.m_lstInterfaces = new List<Interface>();
            this.m_strID = _xmlVertexDefinition.Attributes["id"].Value;

            XmlNodeList xmlElements = _xmlVertexDefinition.SelectNodes("elements/element");
            foreach (XmlElement xmlElement in xmlElements)
            {
                Element vertexElement = new Element(xmlElement);
                if (null != this.GetElementByID(vertexElement.ID))
                {
                    throw new Exception(string.Format("{0} : duplicate {1} element", this.ID, vertexElement.ID));
                }
                this.m_lstElements.Add(vertexElement);
            }

            XmlNodeList xmlInterfaces = _xmlVertexDefinition.SelectNodes("interfaces/interface");
            foreach (XmlElement xmlInterface in xmlInterfaces)
            {
                Interface vertexInterface = new Interface(xmlInterface);
                if (null != this.GetInterfaceByID(vertexInterface.ID))
                {
                    throw new Exception(string.Format("{0} : duplicate {1} element", this.ID, vertexInterface.ID));
                }
                this.m_lstInterfaces.Add(vertexInterface);
            }
        }

        public bool HasElement(string _strSemantic, Type _type)
        {
            Element vertexElement = GetElementByID(_strSemantic);
            if (null != vertexElement)
            {
                return (_type == vertexElement.Type);
            }
            return false;
        }

        public bool HasInterface(string _strInterface)
        {
            return (null != GetInterfaceByID(_strInterface));
        }

        protected Element GetElementByID(string _strID)
        {
            foreach (Element vertexElement in this.m_lstElements)
            {
                if (_strID == vertexElement.ID)
                {
                    return vertexElement;
                }
            }
            return null;
        }

        protected Interface GetInterfaceByID(string _strID)
        {
            foreach (Interface vertexInterface in this.m_lstInterfaces)
            {
                if (_strID == vertexInterface.ID)
                {
                    return vertexInterface;
                }
            }
            return null;
        }

        #region IEnumerable Membres

        public IEnumerator GetEnumerator()
        {
            return this.m_lstElements.GetEnumerator();
        }

        #endregion
    }
}
